package com.rd.sys.common.fileexport;

import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import baseproj.common.exception.BaseServiceException;

import com.rd.sys.common.base.CommonConstants;
import com.rd.sys.common.threadpool.block.BlockingThreadPool;
import com.rd.sys.dto.commmon.base.BaseDto;
import com.rd.sys.dto.commmon.enums.ExportEnum;

/**
 * 导出工具类.
 */
public class ExportUtil {

    /** The Constant logger. */
    private static final Logger logger = LoggerFactory.getLogger(ExportUtil.class);

    /** 导出执行线程池. */
    private static BlockingThreadPool pool = new BlockingThreadPool(
            CommonConstants.ExportConstants.THREAD_POOL_CORE_SIZE,
            CommonConstants.ExportConstants.THREAD_POOL_CORE_MAX_SIZE,
            CommonConstants.ExportConstants.THREAD_POOL_QUEUE_CAPACITY,
            CommonConstants.ExportConstants.THREAD_POOL_KEEP_LIVE_TIME,
            CommonConstants.ExportConstants.THREAD_POOL_BLOCKING_TIME);

    /**
     * 执行导出.
     * 
     * @param response
     *            HttpServletResponse
     * @param type
     *            导出类型
     * @param dto
     *            导出查询条件
     * @throws BaseServiceException
     *             the base service exception
     * @throws Exception
     *             the exception
     * @version
     */
    public static void execute(HttpServletResponse response, ExportEnum.Type type, BaseDto dto)
            throws BaseServiceException, Exception {
        /** 1. 定义导出线程 */
        ExportThread thread = new ExportThread(type, dto);

        /** 2. 在阻塞线程池中执行导出线程 */
        boolean flag = pool.execute(thread);
        if (!flag) {
            throw new ExportOperatorException(ExportOperatorException.POOL_ALREADY_MAX_ERROR);
        }

        File exportFile = thread.getExportFile();
        if (exportFile == null) {
            throw new ExportOperatorException(ExportOperatorException.THREAD_EXECUTE_FAILED_ERROR);
        }

        /** 3. 输出流响应生成的导出文件 */
        FileInputStream fin = null;
        try {
            response.setHeader("Content-disposition", "attachment;filename=" + exportFile.getName());
            response.setContentType("application/octet-stream,charset="
                    + CommonConstants.ExportConstants.EXPORT_FILE_ENCODING);

            fin = new FileInputStream(exportFile);
            FileChannel inChannel = fin.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (true) {
                int ret = inChannel.read(buffer);
                if (ret == -1) {
                    break;
                }
                buffer.flip();
                response.getOutputStream().write(buffer.array(), 0, ret);
                buffer.clear();
            }
        } finally {
            if (fin != null) {
                try {
                    fin.close();
                } catch (Exception ex) {
                    logger.error("close inputstream error", ex);
                }
            }
        }

        /** 4. 将生成的临时文件删除了 */
        try {
            FileUtils.forceDelete(exportFile);
        } catch (Exception ex) {
            logger.error("delete export file error", ex);
        }
    }
}
